/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.metadata.rtcustomization.core;

import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.I18nResource;
import com.inspur.edp.lcm.metadata.api.entity.MetadataProperties;
import com.inspur.edp.lcm.metadata.common.MetadataSerializer;
import com.inspur.edp.lcm.metadata.common.configuration.I18nManagerHelper;
import com.inspur.edp.lcm.metadata.common.context.RuntimeContext;
import com.inspur.edp.lcm.metadata.spi.MetadataI18nService;
import com.inspur.edp.metadata.rtcustomization.api.entity.MetadataStringDto;
import com.inspur.edp.metadata.rtcustomization.common.EnvironmentContext;
import com.inspur.edp.metadata.rtcustomization.common.event.MetadataRtEventBroker;
import com.inspur.edp.metadata.rtcustomization.inner.api.I18nResourceRTService;
import com.inspur.edp.metadata.rtcustomization.inner.api.utils.I18nResourceRTUtils;
import com.inspur.edp.metadata.rtcustomization.spi.event.MetadataRtEventArgs;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.rpc.api.service.RpcClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.util.LinkedHashMap;
import java.util.List;

@Slf4j
public class AbstractMetadataService {
    private static final String DEFAULT_LANGUAGE = "zh-CHS";

    /**
     * 是否国际化应该由开发时语言和运行时语言来确定
     * 如果开发时语言和运行时语言相同，则不需要国际化
     * 如果开发时语言和运行时语言不同，则需要进行国际化
     * 当前开发时语言为zh-CHS
     * 如果扩展开发时语言，则在元数据Header中记录开发时语言
     */
    public GspMetadata getMetadata(String metadataId, boolean isI18n) {
        // 如果运行时语言是zh-CHS，则不需要进行国际化
        isI18n = !DEFAULT_LANGUAGE.equals(CAFContext.current.getLanguage()) && isI18n;
        // 从缓存中获取元数据
        GspMetadata metadata;
        metadata = getMetadataFromCache(metadataId, isI18n);
        if (metadata != null) {
            return metadata;
        }

        // rpc服务获取元数据
        metadata = getMetadataByRpc(metadataId, isI18n);
        if (metadata == null) {
            return null;
        }

        // 异步加缓存
        asyncUpdateCache(metadata, isI18n);

        return metadata;
    }

    public GspMetadata getMetadata(String metadataId) {
        return getMetadata(metadataId, true);
    }

    protected GspMetadata getMetadataFromCache(String metadataId, boolean isI18n) {
        return null;
    }

    protected GspMetadata getMetadataByRpc(String metadataId, boolean isI18n) {
        GspMetadata metadata;
        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("metadataId", metadataId);

        MetadataStringDto metadataStringDto = invokeRpc(client, params);
        if (metadataStringDto == null || StringUtils.isEmpty(metadataStringDto.getMetadataString())) {
            return null;
        }

        metadata = new MetadataSerializer().deserialize(metadataStringDto.getMetadataString(), GspMetadata.class);
        if (metadata.getProperties() == null) {
            metadata.setProperties(new MetadataProperties("", metadataStringDto.getCacheVersion()));
        } else {
            metadata.getProperties().setCacheVersion(metadataStringDto.getCacheVersion());
        }

        if (isI18n) {
            metadata = getI18nMetadata(metadata, RuntimeContext.getLanguage());
        }

        fireMetadataAchievedEvent(metadata);

        return metadata;
    }

    protected MetadataStringDto invokeRpc(RpcClient client, LinkedHashMap<String, Object> params) {
        return null;
    }

    protected void asyncUpdateCache(GspMetadata metadata, boolean isI18n) {
    }

    protected void fireMetadataAchievedEvent(GspMetadata metadata) {
        MetadataRtEventBroker metadataRtEventBroker = SpringBeanUtils.getBean(MetadataRtEventBroker.class);
        metadataRtEventBroker.fireMetadataAchievedEvent(new MetadataRtEventArgs(metadata, EnvironmentContext.env));
    }

    private GspMetadata getI18nMetadata(GspMetadata metadata, String language) {
        GspMetadata i18nMetadata;
        try {
            language = StringUtils.isEmpty(language) ? RuntimeContext.getLanguage() : language;
            I18nResourceRTService i18nResourceRTService = I18nResourceRTUtils.getI18nResourceRTService();
            if (i18nResourceRTService == null) {
                return metadata;
            }

            List<I18nResource> resources = i18nResourceRTService.getI18nResource(metadata, language);
            MetadataI18nService service = I18nManagerHelper.getInstance().getI18nManager(metadata.getHeader().getType());
            if (service != null && resources != null && resources.size() > 0) {
                i18nMetadata = service.merge(metadata, resources);
                return i18nMetadata;
            }
        } catch (Exception e) {
            //TODO 表单强制获取资源项，获取不到时会报错，异常太多，暂时catch住
        }
        return metadata;
    }
}
